/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager.generatedbo;

import com.inspur.edp.bef.bemanager.befexception.BeManagerException;
import com.inspur.edp.bef.bemanager.util.DataValidatorUtil;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.util.DboTransferUtil;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.lcm.databaseobject.api.DatabaseObjectServiceForWebIde;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.util.UUID;
import lombok.var;

/**
 * 生成Dbo实体对象服务
 *
 * @author hanll02
 */
public class GenerateFromDbo {

  public static GenerateFromDbo getInstance() {
    return new GenerateFromDbo();
  }

  private final String exceptionCode = "BeGenerateDbo";
  private final DatabaseObjectServiceForWebIde dtService = SpringBeanUtils
      .getBean(DatabaseObjectServiceForWebIde.class);
  private final MetadataProjectService projectService = SpringBeanUtils
      .getBean(MetadataProjectService.class);

  private GenerateFromDbo() {
  }

  public final GspBizEntityObject convertDboToBizObject(String path, String dboId,
      String primaryKey) {
    DataValidatorUtil.CheckForEmptyString(path, "path");
    DataValidatorUtil.CheckForEmptyString(dboId, "dboId");
    DataValidatorUtil.CheckForEmptyString(primaryKey, "primaryKey");
    DatabaseObjectTableCore dbo = GetDatabaseObjectTable(path, dboId);
    return convertDboToBizObject(dbo, primaryKey);
  }

  public final GspElementCollection ConvertDboColumnsToElements(String path, String dboId,
      java.util.List<String> columnIds, IGspCommonObject parentObject) {
    DataValidatorUtil.CheckForNullReference(columnIds, "columnIds");
    DataValidatorUtil.CheckForEmptyString(path, "path");
    DataValidatorUtil.CheckForEmptyString(dboId, "dboId");
    GspElementCollection elements = new GspElementCollection(parentObject);
    if (columnIds.isEmpty()) {
      return elements;
    }
    DatabaseObjectTableCore dbo = GetDatabaseObjectTable(path, dboId);
    for (String columnId : columnIds) {
      try {
        boolean isMulti = getIsMultiColumn(dbo, columnId);
        GspBizEntityElement ele = convertDboColumnToBizElement(dbo.getColumnById(columnId),
            isMulti);
        elements.add(ele);
      } catch (RuntimeException e) {
        continue;
      }

    }
    return elements;
  }

  private GspBizEntityObject convertDboToBizObject(DatabaseObjectTableCore dbo, String primaryKey) {
    DataValidatorUtil.CheckForNullReference(dbo, "dbo");
    DataValidatorUtil.CheckForNullReference(primaryKey, "primaryKey");
    GspBizEntityObject obj = new GspBizEntityObject();
    obj.setID(UUID.randomUUID().toString());
    obj.setCode(dbo.getCode());
    obj.setName(dbo.getName());
    obj.setRefObjectName(dbo.getId());
    obj.setObjectType(GspCommonObjectType.MainObject);
    boolean hasSetPrimaryKey = false;
    // 主键
    for (DatabaseObjectColumn column : dbo.getColumns()) {
      boolean isMulti = getIsMultiColumn(dbo, column.getId());
      try {
        GspBizEntityElement ele = convertDboColumnToBizElement(column, isMulti);
        obj.getContainElements().add(ele);
        if (primaryKey.equals(column.getId())) {
          obj.getColumnGenerateID().setElementID(ele.getID());
          ele.setIsRequire(true);
          String IDElementLabelId = "ID";
          if (!IDElementLabelId.equals(ele.getLabelID())) {
            ele.setLabelID(IDElementLabelId);
          }
          ele.setCode(IDElementLabelId);
          ele.setName(IDElementLabelId);
          hasSetPrimaryKey = true;
        }
      } catch (Exception e) {
        //TODO 此处Catch异常需要确认
        throw new RuntimeException();
      }

    }

    if (!hasSetPrimaryKey) {
      throw new BeManagerException("", exceptionCode,
          "设置的主键在DBO中不存在，DBOID=" + dbo.getId() + "主键ID=" + primaryKey, null, ExceptionLevel.Error,
          false);
//            throw new BeManagerException(exceptionCode, $"设置的主键在DBO中不存在，DBOID='{dbo.ID}',主键ID='{primaryKey}'");
    }
    return obj;
  }

  private GspBizEntityElement convertDboColumnToBizElement(DatabaseObjectColumn column,
      boolean isMulti) {
    GspBizEntityElement ele = new GspBizEntityElement();
    ele.setID(UUID.randomUUID().toString());
    ele.setLabelID(column.getCode());
    ele.setCode(column.getCode());
    ele.setName(column.getName());
    ele.setColumnID(column.getId());
    ele.setMDataType(DboTransferUtil.getMDataTypeByDataType(column.getDataType(), exceptionCode));
    RefObject<Integer> length = new RefObject<>(0);
    RefObject<Integer> precision = new RefObject<>(0);
    getLengthPrecisionScale(column, length, precision);
    ele.setLength(length.argvalue);
    ele.setPrecision(precision.argvalue);
    ele.setIsRequire(!column.isNullable());
    ele.setIsMultiLanguage(isMulti);
    return ele;
  }

  private DatabaseObjectTableCore GetDatabaseObjectTable(String path, String dboId) {

    var dbo = dtService.getDatabaseObjectById(path, dboId);
//        if (!(dbo instanceof DatabaseObjectTable)) {
//            throw new RuntimeException("根据路径" + path + "及" + dboId + "获取dbo元数据失败。");
//        }
    if (dbo == null) {
      throw new RuntimeException("根据路径" + path + "及" + dboId + "获取dbo元数据失败。");
    }
    return (DatabaseObjectTableCore) dbo;
  }

  /**
   * 解决lcm的长度精度小数位数与beElementDataType中长度精度小数位数中表达不一致问题
   *
   * @param column    数据库对象列
   * @param length    column中长度
   * @param precision column中精度
   */
  private void getLengthPrecisionScale(DatabaseObjectColumn column, RefObject<Integer> length,
      RefObject<Integer> precision) {
    GspElementDataType mdataType = DboTransferUtil
        .getMDataTypeByDataType(column.getDataType(), exceptionCode);
    length.argvalue = 0;
    precision.argvalue = 0;

    // 解决lcm的长度精度小数位数与beElementDataType中长度精度小数位数中表达不一致问题
    switch (mdataType) {
      case String:
        length.argvalue = column.getLength();
        precision.argvalue = 0;
        break;
      case Decimal:
        length.argvalue = column.getPrecision();
        // BE浮点型字段精度不允许为0
        precision.argvalue = column.getScale() == 0 ? 2 : column.getScale();
        break;
      case Boolean:
        length.argvalue = 1;
        precision.argvalue = 0;
        break;
      // 其他 0，0
    }
  }

  private boolean getIsMultiColumn(DatabaseObjectTableCore dbo, String columnId) {
    boolean isExistColumnId = false;
    if (dbo.getType() == DatabaseObjectType.Table) {
      for (String item : ((DatabaseObjectTable) dbo).getMultiLanguageColumns()) {
        if (item != null && item.equals(columnId)) {
          isExistColumnId = true;
          break;
        }
      }
      isExistColumnId = ((DatabaseObjectTable) dbo).isI18NObject() && isExistColumnId;
    }
    if (dbo.getType() == DatabaseObjectType.View) {

      for (String item : ((DatabaseObjectView) dbo).getMultiLanguageColumns()) {
        if (item != null && item.equals(columnId)) {
          isExistColumnId = true;
          break;
        }
      }

      isExistColumnId = ((DatabaseObjectView) dbo).isI18nObject() && isExistColumnId;
    }
    return isExistColumnId;

  }

  /**
   * 节点编号-dbo编号去除[关键应用]前缀
   *
   * @param
   * @return
   */
  private String getObjectCodeWithDboName(String dboCode, String metapath) {
    String appCode = GetAppCode(metapath);
    String strRegex = "^(" + appCode + ")";

//        String result = Regex.Replace(dboCode, strRegex, "");
    String result = strRegex.replace(dboCode, "");
    if (result.length() > 0) {
      return result;
    }
    return dboCode;
  }

  MetadataService service = SpringBeanUtils.getBean(MetadataService.class);

  private String GetAppCode(String metadataPath) {

    var projectPath = projectService.getMetadataProjInfo(metadataPath).getProjectPath();
    return this.service.getGspProjectInfo(projectPath).getAppCode();
  }
}
